package ven.spots;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Date;
import java.util.ArrayList;

import android.util.Log;

public class DatabaseConnector2 {
	
	//private static final String SCRIPT_URL  = "http://www.esux.net/spots/blinkserver.php?";
	private static final String SCRIPT_URL  = "http://csc453-team03.csc.ncsu.edu/blinkServer.php?";
	private final static String DDMS_FILTER_NAME = "database";
	
	/**
	 * Get a list of active spot nodes from the server script.  Parses text
	 * returned by the php server script since VPN access from an Android is
	 * hard to do.
	 * @return Array list of active spot nodes.
	 * @throws IOException - Bummer...
	 */
	public ArrayList<SpotNode> getNodes(String host_mac) throws IOException {
		//Get an DataInputStream from the server script.
		host_mac = host_mac.toUpperCase();
		URL url = new URL(SCRIPT_URL + "action=get_nodes&host_mac=" + host_mac);
		DataInputStream dis;
		dis = new DataInputStream(new BufferedInputStream(url.openStream()));
		
		/*
		 * Parsing routine for the data.  Each spot node will be on its
		 * own line in the following format:
		 * <mac>|<state>|<red>|<green>|<blue>\n
		 * The remainer of this method creates new SpotNode objects from
		 * this data and throws them into an arraylist to return.
		 */
		ArrayList<SpotNode> nodes = new ArrayList<SpotNode>();
		String line;
		while ((line = dis.readLine()) != null) {
            SpotNode node = this.parseNode(line);
            if (node != null) {
            	nodes.add(node);
            }
         }
		return nodes;
	}
	
	/**
	 * Get an ArrayList of SpotData objects representing all data in the remote database
	 * submitted for the spot with ieee address = mac
	 * @param mac - ieee address of the SunSpot to get data for
	 * @return - ArrayList of SpotData objects representing logged data from the spot
	 * 			 with iee address == mac.
	 * @throws IOException - Bummer...
	 */
	public ArrayList<SpotData> getData(String mac) throws IOException {
		mac = mac.toUpperCase();
		URL url = new URL(SCRIPT_URL + "action=get_data&mac=" + mac);
		DataInputStream dis;
		dis = new DataInputStream(new BufferedInputStream(url.openStream()));
		
		/*
		 * Incoming data format:
		 * <mac>|<timestamp>|<light>|<state>|<red>|<green>|<blue>\n
		 * Parse the incoming data line by line and throw SpotData objects into
		 * an ArrayList to return.
		 */
		ArrayList<SpotData> data = new ArrayList<SpotData>();
		String line;
		while ((line = dis.readLine()) != null) {
			line = line.replace("\n", "").trim();
            String tokens[] = line.split("[|]");
            Log.d(DDMS_FILTER_NAME, "line:  " + line);
            Log.d(DDMS_FILTER_NAME, "Tokens Length:  " + tokens.length);
            if (tokens.length == 7) {
            	mac = tokens[0].replace("|", "").trim();
            	int light = Integer.parseInt(tokens[2].replace("|", "").trim());
            	int state = Integer.parseInt(tokens[3].replace("|", "").trim());
            	int red = Integer.parseInt(tokens[4].replace("|", "").trim());
            	int green = Integer.parseInt(tokens[5].replace("|", "").trim());
            	int blue = Integer.parseInt(tokens[6].replace("|", "").trim());
            	Date date = new Date(Long.parseLong(tokens[1].replace("|", "").trim()));
            	SpotData sd = new SpotData();
            	sd.setIeee(mac);
            	sd.setDate(date);
            	sd.setLight(light);
            	sd.setState(state);
            	sd.setRed(red);
            	sd.setGreen(green);
            	sd.setBlue(blue);
            	data.add(sd);
            }
		}
		return data;
	}
	
	/**
	 * A way for a client to set the state of a to flashing
	 *  sunspot as well as what color it is flashing.
	 * @param mac - iee addy of the sunspot
	 * @param r, g, b -> int rgb values [0,255]
	 * @return true if there were no errors. (Will return true even if 
	 *         you specify a mac that does not exist.  Only way to not
	 *         get true is by specifying invalid params that would cause
	 *         a database error or string->int casting error server side.)
	 * @throws IOException - Bummer.
	 */
	public boolean setState(String mac, int r, int g, int b) throws IOException {
		mac = mac.toUpperCase();
		URL url = new URL(SCRIPT_URL + "action=set_node&mac=" +
				mac + "&r=" + r + "&g=" + g + "&b=" + b);
		DataInputStream dis;
		dis = new DataInputStream(new BufferedInputStream(url.openStream()));
		String data = dis.readLine().trim().toLowerCase();
		return data.equals("ok");
	}
	
	/**
	 * Get a node with ieee address == mac from the php server
	 * @param mac - ieee address of the sunspot (xxxx.xxxx.xxxx.xxxx) (hex) 
	 * @return - SpotNode object if it exists in the db and there are no parsing
	 * 			 errors, null otherwise.
	 * @throws IOException - Bummer...
	 */
	public SpotNode getNode(String mac) throws IOException {
		URL url = new URL(SCRIPT_URL + "action=get_node&mac=" + mac);
		DataInputStream dis;
		dis = new DataInputStream(new BufferedInputStream(url.openStream()));
		String data = dis.readLine();
		if (data != null) {
			return parseNode(dis.readLine());
		} else {
			return null;
		}
	}
	
	/**
	 * Method used by getNode and getNodes to parse a text string into
	 * a SpotNode object.  Returns null if there was a parsing error
	 * @param data - line incoming the php server script in the format:
	 * 				<mac>|<state>|<red>|<green>|<blue>\n
	 * @return SpotNode object if there is no parsing error.  Null otherwise.
	 */
	private SpotNode parseNode(String data) {
		data = data.replace("\n", "").trim();
        String tokens[] = data.split("[|]");
        try {
        	String mac = tokens[0].replace("|", "").trim();
	      	int state = Integer.parseInt(tokens[1].replace("|", "").trim());
	       	int red = Integer.parseInt(tokens[2].replace("|", "").trim());
	       	int green = Integer.parseInt(tokens[3].replace("|", "").trim());
	       	int blue = Integer.parseInt(tokens[4].replace("|", "").trim());
	       	SpotNode node = new SpotNode(mac, state);
	       	node.setRed(red);
	       	node.setGreen(green);
	       	node.setBlue(blue);
	       	return node;
        } catch (Exception e) {
        	return null;
        }
	}
}